<?php
/**
 * Author:   tangxiaowen
 * Email:    846506584@qq.com
 * Date:     2019/3/15 0015
 * Describe: 磨盘风控类
 */

namespace app\index\controller\mopan;

use think\Controller;
use app\index\controller\Member;
use app\index\controller\Order;
use think\model\Merge;
use think\Request;
use think\Log;
use app\index\controller\System;

class MoPan extends Controller
{
    //商户编码
    private static $merchantCode;
    //商户密钥
    private static $apiKey;
    //商户私钥
    private static $appSecret;
    //产品编码
    private static $productCode;
    //请求地址
    private static $host;
    //接口版本号
    private static $version;
    //磨盘风控请求地址
    private static $moPanFengKongUrl;
    //磨盘风控数据上传 [放款记录上传API]
    private static $loanRecordUpUrl;
    //磨盘风控数据上传 [还款记录上传API]
    private static $repaymentUpUrl;

    public function __construct()
    {
        parent::__construct();

        //初始化获取磨盘配置文件
        $this->initMoPanConfig();
        //检测消费环境
        $this->checkSysTem();

        //日志初始化保存地址
        $requestName = Request::instance()->module();
        $controllerName = Request::instance()->controller();
        $action = Request::instance()->action();
        $setPath = strtolower("{$requestName}/{$controllerName}/{$action}/");
        Log::init(['path'=>LOG_PATH.$setPath,'type'  => 'file',]);
    }

    public function test(){
        $result = $this->getMoPanIntegral($userId = 6,$orderSn = '201903180209582888',$platform = 'android',$orderType = 1,$orderMoney = '1500',$orderTime = '2019-03-16 11:05:23');
        dump($result);die;
    }

    /**
     * 获取磨盘风控分[风控决策API]
     * @param url $host 请求地址
     * @param int $userId 用户ID
     * @param string $orderSn 订单单号
     * @param string $platform 设备信息 android／ios / h5
     * @param string $orderType 订单类型 1首借 2复借
     * @param int $orderId 订单ID
     * @param datetime $orderTime 订单
     * @return array
     */
    public function getMoPanIntegral($userId,$orderSn,$platform,$orderType,$orderMoney,$orderTime)
    {
        //获取签名
        $time = time();
        $sign = $this->getSign(self::$moPanFengKongUrl,$time);

        //获取用户信息及银行卡信息
        $userAndBankInfo = $this->getUserAndBankInfo($userId);

        //获取用户设备信息
        $orderDevice = ['platform' => $platform];

        //获取用户联系人信息
        $userEmergent = (new Member())->getUserEmergent($userId);

        //获取通讯运营商信息
        $carrierContact = $this->getCarrierContact($userId);

        //获取用户订单信息
        $orderInfo = $this->getOrderInfo($orderMoney,$orderTime);

        //获取用户账单信息
        $billInfo = $this->getBillInfo($userId,$orderType);

        //获取请求基础参数
        $basicsParam = $this->getBasicsParam($sign,self::$moPanFengKongUrl,$time);

        //设置body参数
        $bodyParam = [
            'riskData' => json_encode([
                'tradeNo'          => $orderSn,           //订单单号
                'orderUserProfile' => $userAndBankInfo,   //用户基本信息
                'orderDevice'      => $orderDevice,       //设备信息
                'orderUserEmergent'=> $userEmergent,      //用户紧急联系人信息
                'orderCarrierContact' => $carrierContact, //用户通讯运营商信息
                'borrowInfo'       => $orderInfo,         //订单信息
                'borrowHistoryInfo'=> $billInfo,          //历史信息
            ]),
        ];
        $requestParam = json_encode(array_merge($basicsParam,$bodyParam));
        return $this->curlRequest(self::$host.self::$moPanFengKongUrl,$requestParam);
    }

    /**
     * 设置请求基础参数
     * @param string $sign 签名
     * @param url $url 请求地址
     * @param integer $time 请求时间戳
     * @return array
     */
    public function getBasicsParam($sign,$url,$time)
    {
        $temp = [
            'sign'         => $sign,
            'httpMethod'   => 'POST',
            'requestURL'   => $url,
            'version'      => self::$version,
            'apiKey'       => self::$apiKey,
            'timestamp'    => $time,
            'merchantCode' => self::$merchantCode,
            'productCode'  => self::$productCode,
        ];
        return $temp;
    }

    /**
     * 放款记录上传至磨盘 [放款记录上传API] [定时任务]
     * @param array $data 昨天还款的用户信息
     */
    public function loanRecordUp($data)
    {
        //获取签名
        $time = time();
        $sign = $this->getSign(self::$loanRecordUpUrl,$time);
        $jsonData = json_encode($data);

        //获取请求基础参数
        $basicsParam = $this->getBasicsParam($sign,self::$loanRecordUpUrl,$time);

        //设置body参数
        $bodyParam = [
            'riskData' => $data,
        ];
        $requestParam = json_encode(array_merge($basicsParam,$bodyParam));
        return $this->curlRequest(self::$host.self::$loanRecordUpUrl,$requestParam);
    }

    /**
     * 还款记录上传至磨盘 [还款记录上传API] [定时任务]
     * @param array $data 昨天还款的用户信息
     */
    public function repaymentRecordUp($data)
    {
        //获取签名
        $time = time();
        $sign = $this->getSign(self::$repaymentUpUrl,$time);
        $jsonData = json_encode($data);

        //获取请求基础数据
        $basicsParam = $this->getBasicsParam($sign,self::$repaymentUpUrl,$time);

        //设置body参数
        $bodyParam = [
            'riskData' => $data,
        ];

        $requestParam = json_encode(array_merge($basicsParam,$bodyParam));
        return $this->curlRequest(self::$host.self::$repaymentUpUrl,$requestParam);
    }

    /**
     * 获取订单单号
     * @param int $orderId 订单ID
     * @param integer $orderMoney 借款金额
     * @param datetime $orderTime 借款时间
     * @param int $number 订单期数
     * @param int $period 订单每期时间
     * @return array
     */
    public function getOrderInfo($orderMoney,$orderTime,$number = 1,$period = 1)
    {
        $temp = [
            'duration'       => 1,   //订单期数
            'durationLength' => 1,   //订单每期时间
            'applyDate'      => $orderTime,  //借款时间
            'loanAmount'     => $orderMoney, //借款金额
        ];
        return $temp;
    }

    /**
     * 获取用户信息及银行卡信息
     * @param int $userId 用户ID
     * @return array
     */
    public function getUserAndBankInfo($userId)
    {
        $data = (new Member())->getUserBankSocial($userId);
        $temp = [
            'mobile'     => $data['Mobile'],
            'realName'   => $data['TrueName'],
            'identityNo' => $data['IDCard'],
            'bankNo'     => $data['BankNo'],
            'bankPhone'  => $data['YMobile'],
            'qq'         => $data['QQ'],
            'marriageStatus' => ($data['marry'])?'已婚':'未婚',
            'liveAddress'=> $data['ad_detail'],
        ];
        return $temp;
    }

    /**
     * 获取用户账单信息
     * @param int $userId 用户ID
     * @return array
     */
    public function getBillInfo($userId,$orderType)
    {
        //用户为复借时需要获取用户之前的放款次数及上一笔是否逾期及逾期天数
        if($orderType == 2){
            //获取用户放款次数
            $temp['backPaidCount'] = (new Member())->getUserLoanNum($userId);
        }

        return $tmep = [
            'borrowType' => 1,//用户类型 1新增 2复借
        ];
    }

    /**
     * 获取用户通讯运营商信息
     * @param int $userId 用户ID
     * @return array
     */
    public function getCarrierContact($userId)
    {
        $temp['carrierType'] = 'moxie';//运营商类型/魔蝎

        //魔蝎原始json数据
        $temp['carrierStr'] = (new Member())->getMoXieJson($userId);

        //运营商报告信息
        $carrierReport = (new Member())->getCarrierReportStr($userId);
        $temp['carrierReportStr'] = $carrierReport['ReportData'];
        //运营商抓取时间
        $temp['carrierDate'] = $carrierReport['CreateTime'];

        return $temp;
    }

    /**
     * 生成签名
     * @param string $httpMethod 请求方式
     * @param string $requestUR 请求地址
     * @param string $version 接口版本号
     * @param string $apiKey 商户密钥
     * @param string $timestamp 请求当前时间
     * @param string $merchantCode 商户编码
     * @param string $productCode 产品编码
     * @return string 生成的签名
     */
    public function getSign($url,$time)
    {
        //生成签名的加密数据
        $temp = [
            'httpMethod'   => 'POST',
            'requestURL'   => $url,
            'version'      => self::$version,
            'apiKey'       => self::$apiKey,
            'timestamp'    =>  $time,
            'merchantCode' => self::$merchantCode,
            'productCode'  => self::$productCode,
        ];

        //ASCII 排序 及秘钥拼接
        $asciiStr = ($this->getAscii($temp)).self::$appSecret;
        //转成UTF8编码并MD5加密返回签名
        return md5(urlencode(mb_convert_encoding($asciiStr, 'utf-8')));
    }

    /**
     * 获取 ASCII 码排序
     */
    public function getAscii($params = array())
    {
        if(!empty($params)){
            $p =  ksort($params);
            if($p){
                $str = '';
                foreach ($params as $k=>$val){
                    $str .= $k . $val;
                }
                $strs = rtrim($str, '&');
                return $strs;
            }
        }
        return '';
    }

    /**
     * 校验配置信息
     * @return json
     */
    private function checkConfig()
    {
        if(empty(self::$merchantCode)){
            return json(['code' => '000009','msg' => '缺少商户编码 merchantCode']);
        }
        if(empty(self::$apiKey)){
            return json(['code' => '000009','msg' => '缺少商户秘钥 apiKey']);
        }
        if(empty(self::$appSecret)){
            return json(['code' => '000009','msg' => '缺少商户私钥 appSecret']);
        }
        if(empty(self::$productCode)){
            return json(['code' => '000009','msg' => '缺少产品编码 productCode']);
        }
        if(empty(self::$moPanFengKongUrl)){
            return json(['code' => '000009','msg' => '缺少配置项磨盘风控请求地址']);
        }
    }

    /**
     * 获取磨盘配置信息
     * @return array
     */
    private function initMoPanConfig()
    {
        $data = db('sys_integrate')->alias('i')
            ->join('xb_sys_inteparameter n','i.ID = n.IntegrateID')
            ->where(['i.EName' => 'mopan'])
            ->select();

        if(!$data){
            returnErrorResult('尚未配置支付环境');
        }

        $temp = [];
        foreach ($data as $k=>$v){
            $temp[$v['ParaName']] = $v['ParaValue'];
        }

        if(!$temp || !isset($temp['merchantCode']) || empty($temp['merchantCode'])){
            returnErrorResult('缺少商户编码配置');
        }elseif(!$temp || !isset($temp['apiKey']) || empty($temp['apiKey'])){
            returnErrorResult('缺少商户密钥配置');
        }elseif(!$temp || !isset($temp['appSecret']) || empty($temp['appSecret'])){
            returnErrorResult('缺少商户私钥配置');
        }elseif(!$temp || !isset($temp['productCode']) || empty($temp['productCode'])){
            returnErrorResult('缺少产品编码配置');
        }elseif(!$temp || !isset($temp['host']) || empty($temp['host'])){
            returnErrorResult('缺少请求地址host配置');
        }elseif(!$temp || !isset($temp['version']) || empty($temp['version'])){
            returnErrorResult('缺少接口版本号配置');
        }elseif(!$temp || !isset($temp['moPanFengKongUrl']) || empty($temp['moPanFengKongUrl'])){
            returnErrorResult('缺少磨盘风控请求地址配置');
        }elseif(!$temp || !isset($temp['loanRecordUpUrl']) || empty($temp['loanRecordUpUrl'])){
            returnErrorResult('缺少磨盘风控数据上传[放款记录上传API]配置');
        }elseif(!$temp || !isset($temp['repaymentUpUrl']) || empty($temp['repaymentUpUrl'])){
            returnErrorResult('缺少磨盘风控数据上传[还款记录上传API]配置');
        }

        self::$merchantCode     = $temp['merchantCode'];
        self::$apiKey           = $temp['apiKey'];
        self::$appSecret        = $temp['appSecret'];
        self::$productCode      = $temp['productCode'];
        self::$host             = $temp['host'];
        self::$version          = $temp['version'];
        self::$moPanFengKongUrl = $temp['moPanFengKongUrl'];
        self::$loanRecordUpUrl  = $temp['loanRecordUpUrl'];
        self::$repaymentUpUrl   = $temp['repaymentUpUrl'];
    }

    /**
     * 检测消费环境
     * @return json
     */
    private function checkSysTem()
    {
        $result = (new System())->checkSysTem();
        if(!$result){
            return json(['code' => '000010','msg' => '系统消费余额不足 请联系客服']);
        }
    }

    /**
     * 创建curl请求
     * @param url $url 请求地址
     * @param array $body 请求数据
     */
    public function curlRequest($url,$body)
    {
        $headers[] = "Content-Type:application/json";

        $culObj = curl_init();
        //设置请求的curl
        curl_setopt($culObj, CURLOPT_URL, $url);
        //不输出文件头(直接获取内容部分)
        curl_setopt($culObj, CURLOPT_HEADER, false);
        //设置curl请求方式
        curl_setopt($culObj, CURLOPT_POST, true);
        //设置请求的参数
        curl_setopt($culObj, CURLOPT_POSTFIELDS, $body);
        //将curl_exec()获取的信息以字符串返回，而不是直接输出。
        curl_setopt($culObj, CURLOPT_RETURNTRANSFER, true);
        //禁止 cURL 验证对等证书（peer's certificate）
        curl_setopt($culObj, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($culObj, CURLOPT_HTTPHEADER, $headers);
        //允许Curl函数执行的最长秒数。这里设置为30秒
        curl_setopt($culObj, CURLOPT_TIMEOUT, 30);
        $result = curl_exec($culObj);
        curl_close($culObj);

        return $result;
    }
}